

# 跨度可以是负数，这样会使数组在内存中后向移动，切片中 obj[::-1] 或 obj[:,::-1] 就是如此。
#
# 创建一个 ndarray 只需调用 NumPy 的 array 函数即可：
#
# numpy_test.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

# 参数说明：
#
# 名称	描述
# object	数组或嵌套的数列
# dtype	数组元素的数据类型，可选
# copy	对象是否需要复制，可选
# order	创建数组的样式，C为行方向，F为列方向，A为任意方向（默认）
# subok	默认返回一个与基类类型一致的数组
# ndmin	指定生成数组的最小维度

import numpy

array1 = numpy.array([1, 2, 3])
print("一维数组：", array1)
array2 = numpy.array([[1, 2], [3, 4]])
print("二维数组", array2)
array3 = numpy.array([1, 2, 3, 4, 5], ndmin=2)
print("最小生成的维度：", array3)
array4 = numpy.array([1, 2, 3], dtype=numpy.complex_)
print("元素的类型是复数：", array4)


# 数据类型对象（numpy.dtype 类的实例）用来描述与数组对应的内存区域是如何使用，它描述了数据的以下几个方面：：
#
# 数据的类型（整数，浮点数或者 Python 对象）
# 数据的大小（例如， 整数使用多少个字节存储）
# 数据的字节顺序（小端法或大端法）
# 在结构化类型的情况下，字段的名称、每个字段的数据类型和每个字段所取的内存块的部分
# 如果数据类型是子数组，那么它的形状和数据类型是什么。
# 字节顺序是通过对数据类型预先设定 < 或 > 来决定的。 < 意味着小端法(最小值存储在最小的地址，即低位组放在最前面)。> 意味着大端法(最重要的字节存储在最小的地址，即高位组放在最前面)。
#
# dtype 对象是使用以下语法构造的：
#
# numpy.dtype(object, align, copy)
# object - 要转换为的数据类型对象
# align - 如果为 true，填充字段使其类似 C 的结构体。
# copy - 复制 dtype 对象 ，如果为 false，则是对内置数据类型对象的引用

# 使用标量类型
dt1 = numpy.dtype(numpy.int32)
print("数据类型", dt1)
# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替
dt2 = numpy.dtype('i4')
print("数据类型", dt2)
# 字节顺序标记
dt3 = numpy.dtype('<i4')
print("数据类型", dt3)

# 下面实例展示结构化数据类型的使用，类型字段和对应的实际类型将被创建。
dt4 = numpy.dtype([('age', numpy.int8)])
print("数据对象和类型", dt4)

# 将数据类型应用到ndarray对象中
dt5 = numpy.dtype([('age', numpy.int8)])
array5 = numpy.array([(10,), (20,), (30,)], dtype=dt5)
print("自定义数据类型的数组：", array5)
# 类型字段名可以用于存取实际的 age 列
print(array5['age'])
# 示例定义一个结构化数据类型 student，包含字符串字段 name，整数字段 age，及浮点字段 marks，并将这个 dtype 应用到 ndarray 对象
student = numpy.dtype([('name', 'S20'), ('age', 'i1'), ('marks', 'f4')])
print("学生类型：", student)
stuArray = numpy.array([('tom', 12, 50), ("jerry", 14, 75)], dtype=student)
print("学生数据:", stuArray)
print("学生名字数组：", stuArray['name'])
print("学生年龄数组：", stuArray['age'])
print("学生标记数组：", stuArray['marks'])


# ndarray.ndim
# ndarray.ndim 用于返回数组的维数，等于秩。
arang1 = numpy.arange(24)
print("维度：", arang1.ndim)
# 现在调整大小
arang2 = arang1.reshape(2, 4, 3)
print("维度：", arang2.ndim)

# ndarray.shape
# ndarray.shape 表示数组的维度，返回一个元组，这个元组的长度就是维度的数目，即 ndim 属性(秩)。比如，一个二维数组，其维度表示"行数"和"列数"。
# ndarray.shape 也可以用于调整数组大小。
array6 = numpy.array([[1, 2, 3], [4, 5, 6]])
# 秩是3， 轴是2。下面两个是一样的
array6.shape = (3, 2)
array6.reshape(3, 2)
print("秩是3， 轴是2的数组：", array6)

# ndarray.itemsize
# ndarray.itemsize 以字节的形式返回数组中每一个元素的大小。
#
# 例如，一个元素类型为 float64 的数组 itemsize 属性值为 8(float64 占用 64 个 bits，
# 每个字节长度为 8，所以 64/8，占用 8 个字节），又如，一个元素类型为 complex32 的数组 item 属性为 4（32/8）。

array7 = numpy.array([1, 2, 3, 4, 5], dtype='i1')
print("每个元素占用字节：",  array7.itemsize)
array8 = numpy.array([1, 2, 3, 4, 5], dtype='i4')
print("每个元素占用字节：",  array8.itemsize)

# ndarray.flags
# ndarray.flags 返回 ndarray 对象的内存信息，包含以下属性：
#
# 属性	描述
# C_CONTIGUOUS (C)	数据是在一个单一的C风格的连续段中
# F_CONTIGUOUS (F)	数据是在一个单一的Fortran风格的连续段中
# OWNDATA (O)	数组拥有它所使用的内存或从另一个对象中借用它
# WRITEABLE (W)	数据区域可以被写入，将该值设置为 False，则数据为只读
# ALIGNED (A)	数据和所有元素都适当地对齐到硬件上
# UPDATEIFCOPY (U)	这个数组是其它数组的一个副本，当这个数组被释放时，原数组的内容将被更新
array9 = numpy.array([1, 2, 3, 4, 5])
print("对象内存信息：", array9.flags)


# 创建一个空数组，空数组元素随机值。
array10 = numpy.empty([3, 2], dtype=numpy.int_)
print("空数组：", array10)
# 创建指定大小的数组，数组元素以 0 来填充
# 默认为浮点数
array11 = numpy.zeros(5)
print("指定大小的数组，元素是0：", array11)
# 设置类型为整数
array12 = numpy.zeros((5,), dtype=numpy.int_)
print("设置类型为整数:", array12)
# 自定义类型
array13 = numpy.zeros((5, 2), dtype=[('x', 'i4'), ('y', 'i4')])
print("自定义类型：", array13)

# 默认为浮点数
array14 = numpy.ones(5)
print("默认浮点数类型：", array14)
# 自定义类型
array15 = numpy.ones([2,2], dtype=int)
print("自定义类型：", array15)

# 将列表转换为 ndarray
a = [1, 2, 3]
array16 = numpy.asarray(a)
print("将列表转为ndarray：", array16)
# 将元组转换为 ndarray
t = (1, 2, 3)
array17 = numpy.asarray(t)
print("将元组转为ndarray：    ", array17)
# 将元组列表转换为 ndarray
ta = [(1, 2, 3), (4, 5)]
array18 = numpy.asarray(ta)
print("将元组列表转换为 ndarray：", array18)


# numpy.frombuffer 用于实现动态数组。
# numpy.frombuffer 接受 buffer 输入参数，以流的形式读入转化成 ndarray 对象。
s = b'hello world'
array19 = numpy.frombuffer(s, dtype='S1')
print("流数组：", array19)
# numpy.fromiter 方法从可迭代对象中建立 ndarray 对象，返回一维数组。
# 使用range函数创建列表对象
array20 = range(5)
it = iter(array20)
# 使用迭代器创建ndarray
xa = numpy.fromiter(it, dtype=int)
print("迭代器返回的一维数组：", xa)

# numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象
# 生成 0 到 5 的数组
array21 = numpy.arange(5)
print("生成0到5的数组：", array21)
# 设置返回类型位 float, dtype=float
array21 = numpy.arange(5, dtype=float)
print("生成0到5的浮点数数组：", array21)
# 设置了起始值、终止值及步长
array21 = numpy.arange(10, 20, 2)
print("生成10到20的双数数组：", array21)

# 设置起始点为 1 ，终止点为 10，数列个数为 10
array = numpy.linspace(1, 10, 10)
print("设置起始点为 1 ，终止点为 10，数列个数为 10：", array)
# 设置元素全部是1的等差数列
array = numpy.linspace(1, 1, 10)
print("设置元素全部是1的等差数列：", array)
# 将 endpoint 设为 false，不包含终止值
array = numpy.linspace(10, 20, 5, endpoint=False)
print("将 endpoint 设为 false，不包含终止值：", array)
# 将 endpoint 设为 True，包含终止值
array = numpy.linspace(10, 20, 5, endpoint=True)
print("将 endpoint 设为 True，包含终止值：", array)
# 以下实例设置间距
array = numpy.linspace(10, 20, 5, endpoint=True, retstep=True)
print("以下实例设置间距：", array)
# 拓展例子
array = numpy.linspace(1, 10, 10).reshape([10, 1])
print("拓展例子 以下实例设置间距：", array)

# 默认底数是 10
array = numpy.logspace(1.0, 2.0, num=10)
print("默认底数是 10", array)
# 将对数的底数设置为 2
array = numpy.logspace(0, 9, 10, base=2)
print("将对数的底数设置为 2", array)

# 从索引 2 开始到索引 7 停止，间隔为2
array = numpy.arange(10)
s = slice(2, 7, 2)
print("从索引 2 开始到索引 7 停止，间隔为2：", array[s])
# 也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作
s2 = array[2: 7: 2]
print("start:stop:step 来进行切片操作", s2)
# 多维数组同样适用上述索引提取方法
array = numpy.array([[1, 2, 3], [3, 4, 5], [4, 5, 6]])
# 从某个索引处开始切割
print('从数组索引 a[1:] 处开始切割')
print(array[1:])
# 切片还可以包括省略号 …，来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号，它将返回包含行中元素的 ndarray
print("第2列元素：", array[..., 1])   # 第2列元素
print("第2行元素：", array[1, ...])   # 第2行元素
print("第2列及剩下的所有元素：", array[..., 1:])  # 第2列及剩下的所有元素
